feat(build): emit the routed CLI into host artifacts as bin/<name>.mjs (#387) - #419
Conversation
🦋 Changeset detectedLatest commit: 9edd7ef The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4d57182936
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ngeset PR reference Codex review on #419: check the supported-`cli`-without-layout invariant before the empty-layout early return, reject a `cliBin` layout that names any directory but `bin` or omits `.mjs` (the compiler emits the routed CLI only there), and end the changeset summary with the PR reference.
|
@codex review |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d574883982
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…judgment; changeset patch Codex review on #419: emission, the AB4765 warning, and the registration invariant now use `componentCapabilities ?? capabilities` — the same judgment `inspect` reports — via the new `TargetRegistry.componentCapabilityState` / `hostsComponent` accessors, so a component override can never disagree with what the artifact ships. The changeset is `patch` per the pre-1.0 policy (minor is reserved for breaking changes).
|
@codex review |
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
…ngeset PR reference Codex review on #419: check the supported-`cli`-without-layout invariant before the empty-layout early return, reject a `cliBin` layout that names any directory but `bin` or omits `.mjs` (the compiler emits the routed CLI only there), and end the changeset summary with the PR reference.
|
@codex review |
…judgment; changeset patch Codex review on #419: emission, the AB4765 warning, and the registration invariant now use `componentCapabilities ?? capabilities` — the same judgment `inspect` reports — via the new `TargetRegistry.componentCapabilityState` / `hostsComponent` accessors, so a component override can never disagree with what the artifact ships. The changeset is `patch` per the pre-1.0 policy (minor is reserved for breaking changes).
fdd8433 to
664e79c
Compare
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
…ngeset PR reference Codex review on #419: check the supported-`cli`-without-layout invariant before the empty-layout early return, reject a `cliBin` layout that names any directory but `bin` or omits `.mjs` (the compiler emits the routed CLI only there), and end the changeset summary with the PR reference.
664e79c to
bbd71c2
Compare
…judgment; changeset patch Codex review on #419: emission, the AB4765 warning, and the registration invariant now use `componentCapabilities ?? capabilities` — the same judgment `inspect` reports — via the new `TargetRegistry.componentCapabilityState` / `hostsComponent` accessors, so a component override can never disagree with what the artifact ships. The changeset is `patch` per the pre-1.0 policy (minor is reserved for breaking changes).
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
…ngeset PR reference Codex review on #419: check the supported-`cli`-without-layout invariant before the empty-layout early return, reject a `cliBin` layout that names any directory but `bin` or omits `.mjs` (the compiler emits the routed CLI only there), and end the changeset summary with the PR reference.
…judgment; changeset patch Codex review on #419: emission, the AB4765 warning, and the registration invariant now use `componentCapabilities ?? capabilities` — the same judgment `inspect` reports — via the new `TargetRegistry.componentCapabilityState` / `hostsComponent` accessors, so a component override can never disagree with what the artifact ships. The changeset is `patch` per the pre-1.0 policy (minor is reserved for breaking changes).
bbd71c2 to
bffefff
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bffefff52e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ngeset PR reference Codex review on #419: check the supported-`cli`-without-layout invariant before the empty-layout early return, reject a `cliBin` layout that names any directory but `bin` or omits `.mjs` (the compiler emits the routed CLI only there), and end the changeset summary with the PR reference.
…judgment; changeset patch Codex review on #419: emission, the AB4765 warning, and the registration invariant now use `componentCapabilities ?? capabilities` — the same judgment `inspect` reports — via the new `TargetRegistry.componentCapabilityState` / `hostsComponent` accessors, so a component override can never disagree with what the artifact ships. The changeset is `patch` per the pre-1.0 policy (minor is reserved for breaking changes).
…766) Codex review on #419: a host-emitted `bin/MyPlugin.mjs` is the same file as the generated `bin/myplugin.mjs` on macOS and Windows, so the collision check folds case and names both paths in the diagnostic.
bffefff to
0949355
Compare
|
@codex review |
|
Codex Review: Didn't find any major issues. What shall we delve into next? Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
…ngeset PR reference Codex review on #419: check the supported-`cli`-without-layout invariant before the empty-layout early return, reject a `cliBin` layout that names any directory but `bin` or omits `.mjs` (the compiler emits the routed CLI only there), and end the changeset summary with the PR reference.
…judgment; changeset patch Codex review on #419: emission, the AB4765 warning, and the registration invariant now use `componentCapabilities ?? capabilities` — the same judgment `inspect` reports — via the new `TargetRegistry.componentCapabilityState` / `hostsComponent` accessors, so a component override can never disagree with what the artifact ships. The changeset is `patch` per the pre-1.0 policy (minor is reserved for breaking changes).
…766) Codex review on #419: a host-emitted `bin/MyPlugin.mjs` is the same file as the generated `bin/myplugin.mjs` on macOS and Windows, so the collision check folds case and names both paths in the diagnostic.
0949355 to
1c77d7c
Compare
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
…ngeset PR reference Codex review on #419: check the supported-`cli`-without-layout invariant before the empty-layout early return, reject a `cliBin` layout that names any directory but `bin` or omits `.mjs` (the compiler emits the routed CLI only there), and end the changeset summary with the PR reference.
…judgment; changeset patch Codex review on #419: emission, the AB4765 warning, and the registration invariant now use `componentCapabilities ?? capabilities` — the same judgment `inspect` reports — via the new `TargetRegistry.componentCapabilityState` / `hostsComponent` accessors, so a component override can never disagree with what the artifact ships. The changeset is `patch` per the pre-1.0 policy (minor is reserved for breaking changes).
…766) Codex review on #419: a host-emitted `bin/MyPlugin.mjs` is the same file as the generated `bin/myplugin.mjs` on macOS and Windows, so the collision check folds case and names both paths in the diagnostic.
1c77d7c to
fd20548
Compare
|
Codex Review: Didn't find any major issues. Bravo. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
#387) Installed plugins ship skills, hooks, and script routes but had no way to run the routed CLI without a separate npm install. Every target whose adapter publishes the new `cli` capability (all built-in targets) now receives the compiled command graph as `bin/<plugin-name>.mjs` (+ `-flight.mjs` worker), run as `node <plugin-root>/bin/<plugin-name>.mjs`. Script routes reach it as the `../bin/` sibling of their own `import.meta.url`; skills and hooks through the plugin-root token. Manifest, validation (`cliBin` layout), `inspect` (`cli` component), and `inspect --bundler` know the new directory; a target without the capability omits the bin with AB4765; a host file colliding with the bin path is AB4766. The npm package bin is unchanged.
…ngeset PR reference Codex review on #419: check the supported-`cli`-without-layout invariant before the empty-layout early return, reject a `cliBin` layout that names any directory but `bin` or omits `.mjs` (the compiler emits the routed CLI only there), and end the changeset summary with the PR reference.
…judgment; changeset patch Codex review on #419: emission, the AB4765 warning, and the registration invariant now use `componentCapabilities ?? capabilities` — the same judgment `inspect` reports — via the new `TargetRegistry.componentCapabilityState` / `hostsComponent` accessors, so a component override can never disagree with what the artifact ships. The changeset is `patch` per the pre-1.0 policy (minor is reserved for breaking changes).
The MCP App Rsbuild pass asserts the target root holds nothing but its own HTML, so the routed CLI bin (like scripts, hooks, and MCP entries) must follow it; otherwise a project combining MCP Apps with a generated CLI failed with AB5000 (caught by the packed stdio projection release gate).
…766) Codex review on #419: a host-emitted `bin/MyPlugin.mjs` is the same file as the generated `bin/myplugin.mjs` on macOS and Windows, so the collision check folds case and names both paths in the diagnostic.
fd20548 to
9edd7ef
Compare
main (#419) emits src/cli/** as <target>/bin/<plugin-name>.mjs in every built-in target. Package entries now covers the artifact bin, its state anchor, how Skills, hooks, and scripts reach it, and AB4765/AB4766; the artifact tree in Project structure shows the bin/ entry.
A conflict resolution took a pre-#419 copy of docs/diagnostics.md and dropped the artifact-hosted routed CLI family main had added. The file is main's again, plus the scoped exit-code preamble.
Summary
Closes #387. The routed CLI (
src/cli/**) was compiled only into the npm package build (dist/bin/<name>.js), so a plugin installed from a host artifact had skills telling agents to run<name> statusand a script route meant to forward to it, but nothing to forward to.Decision (emission, framework model): the routed CLI is the same class of surface as
scripts/*.mjs— a self-contained Node module that only needs the artifact root to be a plain directory Node executes from, which every host already relies on formcp/andscripts/. So the build now emits the compiled command graph into every selected host artifact whose adapter publishes a newclicapability, as<target>/bin/<plugin-name>.mjs(+bin/<plugin-name>-flight.mjsreact-server worker when any command renders), invoked asnode <plugin-root>/bin/<plugin-name>.mjs <command> [args]. All five built-in targets (claude,codex,cursor,portable,plugin) publish the capability. The package build's bin emission is unchanged.clicapability row (cliBinCapability) on every built-in adapter; the compositepluginadapter unions the three hosts. A target publishing no row reads as honestunavailable: the bin is omitted,inspectlists aclicomponent skipped asunsupported-capability, and source validation reportsAB4765(warning). Registration rejects an adapter that claims a supportedclicapability without acliBinartifact layout.TargetArtifactLayout.cliBin({ directory: 'bin', allowedSuffixes: ['.mjs'] }) on the standard, portable, and plugin layouts; artifact ownership validation admits it; the manifest records both files withbundleprovenance naming every command route;inspect --bundlerdumps each target's bin composition;BuildResult.compiledCliBinsreports them.AB4766(build error) when a target plan already emitsbin/<name>.mjs/-flight.mjs(e.g. a Claudeclaude.bindirectory shipping the same file name).new URL('../bin/<plugin-name>.mjs', import.meta.url)→spawn(process.execPath, [...]); skills/hooks use the plugin-root token (${CLAUDE_PLUGIN_ROOT}/bin/<plugin-name>.mjs). The composite bundle'sAGENTS.mddocuments the shared executable.bin/), the same fallback as the MCP worker beside it, so a co-installed CLI and server share one store; the npm bin keeps itscwdfallback (stateFallbackoption on the generated entry shells).docs/entry-conventions.md(new “The routed CLI inside host artifacts” section),docs/framework-mode.md,docs/diagnostics.md(AB4765–AB4766, verified unused inorigin/mainand every open PR),packages/agent-bundle/README.md; changeset.changeset/387-artifact-routed-cli.md(agent-bundleminor).Evidence
Local gates on this branch (worktree at
origin/main56b77db):pnpm typecheck— clean.pnpm lint— 0 errors / 0 warnings (1048 files).pnpm test:unit— 2728 passed, 2 failed → both rerun in isolation:mcp-probe-servicepasses;native-claude-contract › fails closed when the candidate plugin…times out at its 5 s budget identically on pristineorigin/mainin this environment (stash-verified), so it is pre-existing and unrelated.pnpm test:route-unit— 37/37.pnpm test:projection— 66/66.pnpm build && pnpm test:integration:run— 78 files, 950 passed, 0 failed, 32 skipped (includes artifact validation and host proofs, plus the newartifact-cli-bin.test.ts).Test plan
tests/artifact-cli-bin.test.ts(integration): one fixture (plain + rendered CLI routes, a plain script route spawning the sibling bin) built forclaude,codex,cursor,portable,pluginand a customlegacy-hostadapter without the capability. Asserts per capable target:bin/<name>.mjs+-flight.mjsexist,node bin/<name>.mjs status ticket-7 --jsonprints the routed JSON, help/version/rendered Markdown/--json/exit-2 usage on the same bin, self-contained (noagent-bundle/cli-entryoragent-bundle/metaimport left);legacy-hosthas nobin/but keepsscripts/; exactly oneAB4765warning; script route forwards argv through the sibling bin; compositeAGENTS.mddocuments it; manifestbundleprovenance namessrc/cli/status.tsandsrc/cli/report.tsx;validateArtifactreports no errors;inspectselects theclicomponent with supported evidence onclaudeand skips itunsupported-capabilityonlegacy-host;inspect --bundlerlists 10 per-target bin entries beside the untoucheddist/bin/<name>.jsentry.${CLAUDE_PLUGIN_ROOT}/bin/<name>.mjslowers to a path the same artifact ships, and that file runs.AB4766:claude: { bin: './host-bin' }shipping<name>.mjsfails the build before any artifact is written.tests/adapter-capability-states.test.ts: every built-in target publishescli+cliBin; a supportedclirow without the layout is rejected at registration; no row is valid and hosts no bin.